package service

import (
	"context"
	"go.mongodb.org/mongo-driver/bson"
	"go.mongodb.org/mongo-driver/mongo/options"
	"monitoring-api/models"
	"monitoring-api/serializer"
	"sort"
	"strconv"
	"strings"
)

type PerCondition struct {
	DCL  string `json:"dcl,omitempty"` // dom渲染完毕时间，查询时间范围内的数据，格式为两个数字，中间用_分割，单位毫秒
	DNS  string `json:"dns,omitempty"` // dns解析耗时，查询时间范围内的数据，格式为两个数字，中间用_分割，单位毫秒
	Fcp  string `json:"fcp,omitempty"` // 内容首次绘制时间，查询时间范围内的数据，格式为两个数字，中间用_分割，单位毫秒
	FP   string `json:"fp,omitempty"`  // 首屏渲染时间，查询时间范围内的数据，格式为两个数字，中间用_分割，单位毫秒
	L    string `json:"l,omitempty"`   // 页面完全加载时间，查询时间范围内的数据，格式为两个数字，中间用_分割，单位毫秒
	Lcp  string `json:"lcp,omitempty"` // 最大内容开始绘制时间，查询时间范围内的数据，格式为两个数字，中间用_分割，单位毫秒
	Time string `json:"time"`          // 时间范围，查询起止时间内的数据，格式为两个时间戳，中间用_分割
	URL  string `json:"url,omitempty"` // 页面路径，查询路径中包含参数的数据
}

type GetPerLogsService struct {
	WebID     int64 `json:"web_id"`
	Page      int64 `json:"page"`
	Condition PerCondition
}

func (service *GetPerLogsService) Query() serializer.Response {
	logs := make([]models.Per, 0)
	err, startTime, endTime, url := service.handleCondition()
	_, DCL1, DCL2 := HandleTime(service.Condition.DCL)
	_, DNS1, DNS2 := HandleTime(service.Condition.DNS)
	_, Fcp1, Fcp2 := HandleTime(service.Condition.Fcp)
	_, Fp1, Fp2 := HandleTime(service.Condition.FP)
	_, L1, L2 := HandleTime(service.Condition.L)
	_, Lcp1, Lcp2 := HandleTime(service.Condition.Lcp)
	//查询语句
	filter := bson.D{{"webid", service.WebID},
		{"time", bson.D{{"$gt", startTime}}},
		{"time", bson.D{{"$lte", endTime}}},
		{"url", bson.D{{"$regex", url}}},
		{"dcl", bson.D{{"$gt", DCL1}}},
		{"dcl", bson.D{{"$lte", DCL2}}},
		{"dns", bson.D{{"$gt", DNS1}}},
		{"dns", bson.D{{"$lte", DNS2}}},
		{"fcp", bson.D{{"$gt", Fcp1}}},
		{"fcp", bson.D{{"$lte", Fcp2}}},
		{"fp", bson.D{{"$gt", Fp1}}},
		{"fp", bson.D{{"$lte", Fp2}}},
		{"l", bson.D{{"$gt", L1}}},
		{"l", bson.D{{"$lte", L2}}},
		{"lcp", bson.D{{"$gt", Lcp1}}},
		{"lcp", bson.D{{"$lte", Lcp2}}},
	}
	opts := options.Find().SetSkip((service.Page - 1) * 10).SetLimit(10)
	//获取文档总数
	total, err := models.Mongo.Collection("performances").CountDocuments(context.TODO(), filter)
	//分页查询
	cursor, err := models.Mongo.Collection("performances").Find(context.TODO(), filter, opts)
	if err != nil {
		return serializer.Response{
			Code:    500,
			Message: "数据库查询错误",
			Error:   err.Error(),
		}
	}
	// display the results
	var results []bson.M
	if err = cursor.All(context.TODO(), &results); err != nil {
		return serializer.Response{
			Code:    500,
			Message: "服务器错误",
			Error:   err.Error(),
		}
	}
	for _, result := range results {
		log := models.Per{}
		log.Kind = result["kind"].(int64)
		log.Time = result["time"].(int64)
		log.URL = result["url"].(string)
		log.WebID = result["webid"].(int64)
		log.Lcp = result["lcp"].(int64)
		log.L = result["l"].(int64)
		log.FP = result["fp"].(int64)
		log.Fcp = result["fcp"].(int64)
		log.DNS = result["dns"].(int64)
		log.DCL = result["dcl"].(int64)
		logs = append(logs, log)
	}
	//按时间降序排列
	sort.Slice(logs, func(x, y int) bool {
		return logs[x].Time > logs[y].Time
	})
	return serializer.BuildPerResponse(logs, total, service.Page)
}

// 处理查询条件
func (service *GetPerLogsService) handleCondition() (error, int64, int64, string) {
	//处理时间
	time := strings.Split(service.Condition.Time, "_")
	startTime, err := strconv.ParseInt(time[0], 10, 64)
	if err != nil {
		return err, 0, 0, ""
	}
	endTime, err := strconv.ParseInt(time[1], 10, 64)
	if err != nil {
		return err, 0, 0, ""
	}
	//处理url
	var url string
	if service.Condition.URL != "" {
		url = service.Condition.URL
	} else {
		url = ""
	}
	return err, startTime, endTime, url
}

func HandleTime(TimeStr string) (error, int64, int64) {
	var err error
	var startTime, endTime int64
	if TimeStr == "" {
		return err, 0, 9999999
	} else {
		//处理时间
		time := strings.Split(TimeStr, "_")
		startTime, err = strconv.ParseInt(time[0], 10, 64)
		if err != nil {
			return err, 0, 0
		}
		endTime, err = strconv.ParseInt(time[1], 10, 64)
		if err != nil {
			return err, 0, 0
		}
		return err, startTime, endTime
	}
}
